package org.example.heterogeneous.readData;

import lombok.Data;
import org.example.heterogeneous.AdjacencyEdge;
import org.example.heterogeneous.Edge;
import org.example.heterogeneous.Node;
import org.example.heterogeneous.Utils;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/***
 * Foursquare数据
 * 该数据集包括2012年4月12日至2013年2月16日从Foursquare收集的纽约市和东京的长期（约10个月）签到数据。
 * 它包含两个 tsv 格式的文件。 每个文件包含 8 列，分别是：
 *
 * 1. 用户ID（匿名）
 * 2. 场地ID（Foursquare）
 * 3. 场馆类别ID（Foursquare）
 * 4. 场馆类别名称（Fousquare）
 * 5. 纬度
 * 6. 经度
 * 7. 时区偏移量（以分钟为单位）（本次签到发生时与 UTC 同一时间之间的偏移量（以分钟为单位））
 * 8. 世界标准时间
 *
 * 文件 dataset_TSMC2014_NYC.txt 包含纽约市的 227428 次签到。
 * 文件 dataset_TSMC2014_TKY.txt 包含东京的 573703 次签到。
 */
@Data
public class FoursquareData {

    private int start = 0;

    private int end = 0;

    // 输入的边
    private List<Edge> edgeList;

    // 输入的顶点集合
    private List<Node> nodeList;

    // 邻接表
    private List<AdjacencyEdge> adjacencyEdgeList;

    private int[] first;

    // user顶点类型为1
    private static final int USER_TYPE = 1;

    // venue顶点类型为2
    private static final int VENUE_TYPE = 2;

    // venueCategory顶点类型为3
    private static final int VENUECATEGORY_TYPE = 3;

    public void readTSMC2014(String inputFileName, String regex) {
        try {
            BufferedReader reader = new BufferedReader(new FileReader(inputFileName));
            String line;

            // 标识顶点是否已经存储
            Map<String, Integer> userExist = new HashMap<>();
            Map<String, Integer> venueExist = new HashMap<>();
            Map<String, Integer> venueCategoryExist = new HashMap<>();

            // 标识边(x,y)是否已经存储
            Map<String, Boolean> edgeExist = new HashMap<>();

            edgeList = new ArrayList<>();
            int index = 0;
            nodeList = new ArrayList<>();
            String str;
            int x, y;
            int userIndex, venueIndex, venueCategoryIndex;
            String userId, venueId, venueCategoryId;

            while ((line = reader.readLine()) != null) {
                String[] words = line.split(regex);
                // 去掉格式不符合的数据
                if (words.length != 8) {
                    continue;
                }
                userId = words[0].trim();
                venueId = words[1].trim();
                venueCategoryId = words[2].trim();

                if (!userExist.containsKey(userId)) {
                    Node user = new Node(index++, USER_TYPE, userId);
                    nodeList.add(user);
                    userExist.put(userId, user.getId());
                    userIndex = user.getId();
                } else {
                    userIndex = userExist.get(userId);
                }
                if (!venueExist.containsKey(venueId)) {
                    Node venue = new Node(index++, VENUE_TYPE, venueId);
                    nodeList.add(venue);
                    venueExist.put(venueId, venue.getId());
                    venueIndex = venue.getId();
                } else {
                    venueIndex = venueExist.get(venueId);
                }
                if (!venueCategoryExist.containsKey(venueCategoryId)) {
                    Node venueCategory = new Node(index++, VENUECATEGORY_TYPE, venueCategoryId);
                    nodeList.add(venueCategory);
                    venueCategoryExist.put(venueCategoryId, venueCategory.getId());
                    venueCategoryIndex = venueCategory.getId();
                } else {
                    venueCategoryIndex = venueCategoryExist.get(venueCategoryId);
                }

                // user-venue
                x = Math.min(userIndex, venueIndex);
                y = userIndex ^ venueIndex ^ x;
                str = x + "-" + y;
                // 去除重边
                if (!edgeExist.containsKey(str)) {
                    edgeExist.put(str, true);
                    edgeList.add(new Edge(x, y));
                }

                // user-venueCategory
                x = Math.min(userIndex, venueCategoryIndex);
                y = userIndex ^ venueCategoryIndex ^ x;
                str = x + "-" + y;
                // 去除重边
                if (!edgeExist.containsKey(str)) {
                    edgeExist.put(str, true);
                    edgeList.add(new Edge(x, y));
                }

                // venue-venueCategory
                x = Math.min(venueIndex, venueCategoryIndex);
                y = venueIndex ^ venueCategoryIndex ^ x;
                str = x + "-" + y;
                // 去除重边
                if (!edgeExist.containsKey(str)) {
                    edgeExist.put(str, true);
                    edgeList.add(new Edge(x, y));
                }

            }
            end = nodeList.size();
            reader.close();

            first = new int[end + 1];
            // 邻接表存储边
            adjacencyEdgeList = Utils.addEdge(edgeList, end, first);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }



    public void readubicomp2013(String inputFileName, String regex) {
        try {
            BufferedReader reader = new BufferedReader(new FileReader(inputFileName));
            String line;

            // 标识顶点是否已经存储
            Map<String, Integer> userExist = new HashMap<>();
            Map<String, Integer> venueExist = new HashMap<>();


            // 标识边(x,y)是否已经存储
            Map<String, Boolean> edgeExist = new HashMap<>();

            edgeList = new ArrayList<>();
            int index = 0;
            nodeList = new ArrayList<>();
            String str;
            int x, y;
            int userIndex, venueIndex;
            String userId, venueId;

            while ((line = reader.readLine()) != null) {
                String[] words = line.split(regex);
                // 去掉格式不符合的数据
                if (words.length != 2) {
                    continue;
                }
                userId = words[0].trim();
                venueId = words[1].trim();

                if (!userExist.containsKey(userId)) {
                    Node user = new Node(index++, USER_TYPE, userId);
                    nodeList.add(user);
                    userExist.put(userId, user.getId());
                    userIndex = user.getId();
                } else {
                    userIndex = userExist.get(userId);
                }
                if (!venueExist.containsKey(venueId)) {
                    Node venue = new Node(index++, VENUE_TYPE, venueId);
                    nodeList.add(venue);
                    venueExist.put(venueId, venue.getId());
                    venueIndex = venue.getId();
                } else {
                    venueIndex = venueExist.get(venueId);
                }


                // user-venue
                x = Math.min(userIndex, venueIndex);
                y = userIndex ^ venueIndex ^ x;
                str = x + "-" + y;
                // 去除重边
                if (!edgeExist.containsKey(str)) {
                    edgeExist.put(str, true);
                    edgeList.add(new Edge(x, y));
                }

            }
            end = nodeList.size();
            reader.close();

            first = new int[end + 1];
            // 邻接表存储边
            adjacencyEdgeList = Utils.addEdge(edgeList, end, first);

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
